import SwiftSyntax

// MARK: - Indent

/// Indent level + tabs or spaces per indent.
public struct Indent
{
    public let level: Int
    public let perIndent: PerIndent

    func incrementLevel() -> Indent
    {
        return Indent(level: self.level + 1, perIndent: self.perIndent)
    }

    var triviaPiece: TriviaPiece
    {
        switch self.perIndent {
        case let .spaces(perIndent):
            return .spaces(self.level * perIndent)
        case let .tabs(perIndent):
            return .tabs(self.level * perIndent)
        }
    }
}

// MARK: - PerIndent

/// Number of tabs or spaces per indent level.
public enum PerIndent: Equatable
{
    /// A space ' ' character.
    case spaces(Int)

    /// A tab '\t' character.
    case tabs(Int)

    var string: String
    {
        switch self {
        case let .spaces(perIndent):
            return String(repeating: " ", count: perIndent)

        case let .tabs(perIndent):
            return String(repeating: "\t", count: perIndent)
        }
    }
}

// MARK: - IndentStrategy

/// Indent strategy used in `TokenSyntax.withIndent(strategy:)`.
enum IndentStrategy
{
    /// Use `Indent` (tabs or spaces).
    ///
    /// - `skipsCommentedLine`:
    ///   Skips indenting when line is commented-out, e.g. comments generated by Xcode's "Cmd + /".
    ///
    /// - `adjustsLeadingTriviaComment`:
    ///   Workaround for comment's indent before closing token (e.g. `}`).
    ///   For example, in `func foo() {\n// comment\n}`, **right-brace has comment leadingTrivia**,
    ///   so it's difficult to make comment's indent based on `}`'s indent level.
    ///   In such case, set `adjustsLeadingTriviaComment = true` to temporarily increase comment's indent.
    case useIndent(
        indent: Indent,
        skipsCommentedLine: Bool,
        adjustsLeadingTriviaComment: Bool
    )

    /// Force-spaced indent by `FirstItemAwareIndenter`
    /// for aligning items based on 1st item's position.
    case forcedSpaces(spaces: Int)
}
